<template>
  <div class="scroll-reveal-container" ref="container"
    :style="{ '--delay': delay + 'ms', '--duration': duration + 'ms' }">
    <slot :isVisible="isVisible" />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

const props = withDefaults(defineProps<{
  threshold?: number      // 触发可见比例 (0-1)
  offset?: string         // 触发偏移量 ('100px' 或 '20%')
  duration?: number       // 动画持续时间 (ms)
  delay?: number          // 动画延迟时间 (ms)
  once?: boolean          // 是否仅执行一次
  rootMargin?: string     // 观察器边界 (默认 '0px')
}>(), {
  threshold: 0.2,
  offset: '0px',
  duration: 800,
  delay: 0,
  once: true,
  rootMargin: '0px'
})

const emit = defineEmits(['reveal'])
const container = ref<HTMLElement | null>(null)
const isVisible = ref(false)
let observer: IntersectionObserver | null = null

onMounted(() => {
  if (!container.value) return

  // 配置观察选项
  const options: IntersectionObserverInit = {
    root: null,
    rootMargin: props.rootMargin,
    threshold: props.threshold
  }

  observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        isVisible.value = true
        emit('reveal')
        if (props.once && observer) {
          observer.unobserve(entry.target)
        }
      }
    })
  }, options)

  observer.observe(container.value)
})

onUnmounted(() => {
  if (observer) observer.disconnect()
})
</script>

<style lang="scss" scoped>
.scroll-reveal-container {
  opacity: 0;
  transform: translateY(calc(v-bind('props.offset')));
  transition:
    opacity var(--duration) ease-out var(--delay),
    transform var(--duration) cubic-bezier(0.22, 0.61, 0.36, 1) var(--delay);

  &.is-visible {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>
